package org.japo.java.entities;

import java.util.Calendar;
import java.util.GregorianCalendar;

public class Fecha {

    // Referencias
    public static final String[] DIAS = {"lunes", "martes", "miércoles",
        "jueves", "viernes", "sábado", "domingo"};

    public static final String[] MESES = {"enero", "febrero", "marzo",
        "abril", "mayo", "junio", "julio", "agosto", "septiembre",
        "octubre", "noviembre", "diciembre"};

    public static final String[] ESTACIONES = {"primavera", "verano",
        "otoño", "invierno"};

    // Variables
    private int dia;
    private int mes;
    private int any;

    // Constructores
    public Fecha() {
        establecerFechaSistema();
    }

    public Fecha(int dia, int mes, int any) {
        if (validarFecha(dia, mes, any)) {
            this.dia = dia;
            this.mes = mes;
            this.any = any;
        } else {
            establecerFechaSistema();
        }
    }

    // Accesores
    public int getDia() {
        return dia;
    }

    public void setDia(int dia) {
        if (validarFecha(dia, mes, any)) {
            this.dia = dia;
        }
    }

    public int getMes() {
        return mes;
    }

    public void setMes(int mes) {
        if (validarFecha(dia, mes, any)) {
            this.mes = mes;
        }
    }

    public int getAny() {
        return any;
    }

    public void setAny(int any) {
        if (validarFecha(dia, mes, any)) {
            this.any = any;
        }
    }

    public static boolean validarFecha(int dia, int mes, int any) {
        return dia >= 1 && dia <= 31
                && (mes == 1 || mes == 3 || mes == 5
                || mes == 7 || mes == 8 || mes == 10
                || mes == 12)
                || dia >= 1 && dia <= 30
                && (mes == 4 || mes == 6 || mes == 9
                || mes == 11)
                || dia >= 1 && dia <= 29 && mes == 2
                && (any % 400 == 0
                || any % 100 != 0 && any % 4 == 0)
                || dia >= 1 && dia <= 28 && mes == 2;
    }

    public void mostrarFechaCorta() {
        System.out.println(toString());
    }

    public void mostrarFechaLarga() {
        System.out.printf("%d de %s de %d\n", dia, MESES[mes - 1], any);
    }
    
    @Override
    public boolean equals(Object o) {
        // Semáforo de comparación
        boolean testOK;
        
        // Proceso de detección
        if (o == null) {
            testOK = false;
        } else if (!(o instanceof Fecha)) {
            testOK = false;
        } else {
            Fecha fecha = (Fecha) o;
            testOK = this.dia == fecha.dia &&
                     this.mes == fecha.mes &&
                     this.any == fecha.any;
        }
        
        // Resultado del análisis
        return testOK;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 31 * hash + this.dia;
        hash = 31 * hash + this.mes;
        hash = 31 * hash + this.any;
        return hash;
    }

    @Override
    public String toString() {
        return String.format("%02d/%02d/%4d", dia, mes, any);
    }

    private void establecerFechaSistema() {
        // Instancia objeto GregorianCalendar
        GregorianCalendar gc = new GregorianCalendar();

        // Obtener la hora
        dia = gc.get(Calendar.DAY_OF_MONTH);
        mes = gc.get(Calendar.MONTH) + 1;
        any = gc.get(Calendar.YEAR);
    }
    
    public static boolean validarBisiesto(int any) {
        return any % 400 == 0 ||
               any % 100 != 0 &&
               any %   4 == 0;
    }
    
    public static int calcularDiasMes(int mes, int any) {
        // Resultado
        int dias;
        
        // Semaforos de situación
        boolean b31OK = mes == 3  || mes == 5 || mes == 7 || mes == 8 ||
                        mes == 10 || mes == 12;
        boolean b30OK = mes == 4  || mes == 6 || mes == 9 || mes == 11;
        boolean b29OK = mes == 2  && validarBisiesto(any);
        
        // Análisis
        if (b31OK) {
            dias = 31;
        } else if (b30OK) {
            dias = 30;
        } else if (b29OK) {
            dias = 29;
        } else if (mes == 2) {
            dias = 28;
        } else {
            dias = 0;
        }
        
        // Resultado
        return dias;
    }
}
